#ifndef __IRDECODER_H__
#define __IRDECODER_H__

/* INFRARED  PROTOCOL
 * --------------------------------------------------------------------------
 * The infrared protocol is used to control the movement of the quadpod.
 * The reception and demodulation is done by dedicated IC - OS1838, which is 
 * budget alternative to Vishal's TSOP31238. The circuit demodulates the 
 * incoming IR signal and sends inverted output to the micro controller.  
 * The signal is intercepted on the external interrupt pin INT0 and the 
 * interrupt handler implements a simple FSM to decode the signal.
 *
 * The used protocol is Mitsubishi IR, which has following characteristic:
 *
 * Protocol timing:
 * ----------------
 *
 *  |<----- Logical 0 ----->|<--------- Logical 1 ------------>|
 *  |                       |                                  |
 *  +-----------+           +-----------+                      +
 *  |||||||||||||           |||||||||||||                      ||||
 *  |||||||||||||           |||||||||||||                      ||||
 *  |||||||||||||           |||||||||||||                      ||||
 *  |||||||||||||           |||||||||||||                      ||||
 *  |||||||||||||           |||||||||||||                      ||||
 *  +|||||||||||+-----------+|||||||||||+----------------------+|||
 *  |           |           |           |                      |
 *  |<--526us-->|           |<--526us-->|                      |
 *  |                       |                                  |
 *  |<------- 1 ms -------->|<-------------- 2 ms ------------>|
 *
 *  Protocol pulse train:
 *  ---------------------
 *  (is displayed correctly with the font "DeJavu Sans Mono")
 *
 *               1  0 0 1  1  0 0 0      1  0 0 1  1  0 0 0
 *  ▉▉▉▉▉▉▉▉    ▉  ▉ ▉ ▉  ▉  ▉ ▉ ▉ ▉    ▉  ▉ ▉ ▉  ▉  ▉ ▉ ▉ ▉  
 *  ▉▉▉▉▉▉▉▉    ▉  ▉ ▉ ▉  ▉  ▉ ▉ ▉ ▉    ▉  ▉ ▉ ▉  ▉  ▉ ▉ ▉ ▉  
 *  ▉▉▉▉▉▉▉▉    ▉  ▉ ▉ ▉  ▉  ▉ ▉ ▉ ▉    ▉  ▉ ▉ ▉  ▉  ▉ ▉ ▉ ▉  
 *  |      |    |LSB            MSB|    |LSB            MSB|
 *  |--8ms-|-4ms|                  |-4ms|                  |
 *  |           |<---- Address --->|    |<--- Command ---->|
 *
 *
 *  Plain ASCII graphic for the same:
 *
 *               1  0 0 1  1  0 0 0      1  0 0 1  1  0 0 0
 *  MMMMMMMM    M  M M M  M  M M M M    M  M M M  M  M M M M  
 *  MMMMMMMM    M  M M M  M  M M M M    M  M M M  M  M M M M  
 *  MMMMMMMM    M  M M M  M  M M M M    M  M M M  M  M M M M  
 *  |      |    |LSB            MSB|    |LSB            MSB|
 *  |--8ms-|-4ms|                  |-4ms|                  |
 *  |           |<---- Address --->|    |<--- Command ---->|
 *
 *  The decoder ignores the address, delivers just the decoded command. 
 *  Following table delivers used codes supported by quadpod:
 */

#define	IRC_REVERSE		0x4D // X-Sat code <Down>
#define	IRC_FORWARD		0x4C // X-Sat code <Up>
#define	IRC_LEFT			0x53 // X-Sat code <4>
#define	IRC_RIGHT		0x46 // X-Sat code <TIMER>
#define	IRC_STOP			0x41 // X-Sat code <Power>
#define  IRC_STRAIGHT	0x4A // X-Sat code <MONO>
#define  IRC_ROTATE		0x4B // X-Sat code <STEREO>
#define  IRC_SLOWER		0x4E // X-Sat code <9>
#define  IRC_FASTER		0x57 // X-Sat code <8>
#define  IRC_HIGHER		0x48 // X-Sat code <TV/SAT>
#define  IRC_LOWER		0x47 // X-Sat code <RECALL>
#define	IRC_GAIT			0x40 // X-Sat code <Mute>

/* X-Sat codes. The table lists the codes used in the quadpod to control its 
 * movement. The codes can been determined by logic analyser when reading
 * the IR signal from the used remote control.
 */ 

#define	TOP		0xFF

#define	IRDCNTR	86 // TCCN
/* The FSM is using INT0 to detect the falling edge of the inverted pulse
 * train delivered by the IR demodulator. The internal timer0/counter0
 * is used to support the decoding. The timer0 is prescaled by 256 and configured
 * for CTC mode. The interrupt fires when timer0 reaches value of IRDCNTR. The
 * counting takes him 1,50 ms. 
 *
 * The decoding schema is described
 * in the ISR handler itself in the main logic. This document duplicated the
 * section:
 *
 * The state diagram for the decoding FSM is depicted here:
 *
 *        INT0
 *         |
 *     | TCNT0=0 |
 *     | get IRC |        +-----/ RUN > 7? /---> yes ---> | set FINISH | ---> reti()
 *     |reset IRC|        |          |
 *         |              |          no
 *         |              |          |
 *    / DECODING? /--yes--+      / ICR < 2? / ---> no ---> | set IDLE | ---> reti()
 *         |                         |
 *         |                        yes
 *         |                         |
 *        no                | CODE |= (IRC<<RUN) |
 *         |                |      RUN++         |
 *         |                         |
 *         |                      reti()
 *         |
 *    / STEADY? /--yes--> / IRC == 3? /---> yes ---> | set DECODING | ---> reti() 
 *         |                    |                    |    RUN = 0   |
 *         |                    no
 *         |                    |
 *         |                | RUN++ |
 *         |                    |
 *         |               / RUN > 7? / ---> yes ---> | set IDLE | ---> reti()  
 *        no                    |
 *         |                   no
 *         |                    |
 *         |                  reti()
 *         |
 *   / IRC == 8? /---> yes ---> | set STEADY | ---> reti()
 *         |                    |   RUN = 0  |
 *        no
 *         |
 *       reti()  
 *
 *   LEGEND:
 *   ---------------------------------------------------------------------------
 *   TCNT0   Timer/Couner0.
 *   IRC     IR pulse train counter. This counts 1,5 millisecond long intervals 
 *           between two incoming falling edges of the signal.
 *   RUN     internal variable inside ISR(INT0). It counts bits in the address
 *           and command. It does not let the decoder to overflow.
 *
 */

enum decoder_status_t {
	IDLE = 0,
	STEADY,
	DECODING,
	FINISHED,
	ERROR,
};
typedef enum decoder_status_t decoder_status_t;

struct decoder_t {
	uint8_t	cntr;
	uint8_t	code;
	uint8_t	status;
	uint8_t	debounce;
};
typedef struct decoder_t decoder_t;


#endif // __IRDECODER_H__
